python paramiko模块

python模块之paramiko模块

paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。paramiko支持Linux, Solaris, BSD, MacOS X, Windows等平台通过SSH从一个平台连接到另外一个平台。利用该模块,可以方便的进行ssh连接和sftp协议进行sftp文件传输。

paramiko包里一共有种连接方式(两个类):SSHClient和Transport,每种连接方式都支持口令认证和证书认证。

paramiko也有一些其它的方法和属性。本文只介绍简单、常用的。

paramiko不是python基本模块,需是基于pycrypto模块,所以需要安装pycrypto,再安装paramiko

1
2
3
4
5
pip3 install pycrypto # windows下多半是会报错的,原因是因为需要安装c++,并且设置变量。

pip3 install paramiko
# 实际上直接安装paramiko,自动安装依赖的包。我使用的pip版本是pip 9.0.3
# 成功的时候会提示安装了下面这些包:pycparser, cffi, pynacl, bcrypt, pyasn1, asn1crypto, cryptography, paramiko

paramiko—->SSHClient类——–>口令认证 证书认证

paramiko—->Transport类——–>口令认证 证书认证

一、SSHClient:用来远程执行命令

方法/属性名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
1.connect()
参数/参数类型:
hostname(str:主机ip 必须参数)
port(int:端口 必须参数)
username(str:用户名 用户名和pkey密钥连接方式必须存在一个)
password(str:密码)
pkey(pkey:密钥)
timeout(float:超时时间 可选)
allow_agent(bool:当为flase时,禁用连接到ssh代理 可行)
look_for_keys(bool:flase时,禁用在~/.ssh中搜索秘钥文件 可选)
compress(bool:true时打开压缩 可选)


2.exec_command()远程执行命令,popen远程版
command(str:远程执行的命令,如果有多个命令需要操作时,需要通过分号进行分割)
bufsize(int:缓冲区的大小默认为-1,无限制)

3.load_system_host_keys()加载本地公秘钥校验文件,默认为~/.ssh/known_hosts
filename(str:远程主机公钥记录文件,linux系统下默认路径~/.ssh/known_hosts)

4.set_missing_host_key_policy()
连接主机没有本地主机秘钥或者HostKeys对象时策略,目前支持三种:AutoAddPolicy,RejectPolicy,WarningPolicy
AutoAddPolicy:自动添加主机名以及主机密钥

RejectPolicy(默认):自动拒绝未知的主机名和秘钥

WarningPolicy: 用于记录一个未知主机秘钥的Python警告

示例:

ssh = paramiko.SSHClient()

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

ssh.connect(.................)

stdin.wirte(str) str 输入str型的字符确认继续。应该类似bat 中的pause

二、Transport:用来上传下载远程主机的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
方法/属性名 作用 参数 示例
Transport((主机名,端口号))
建立远程主机加密码管道对象
主机名:ip或者主机名,str型
端口号:指定端口,int型
sf = paramiko.Transport(("192.168.1.1",22))

connect(username,password)
建立远程连接
username:用户名
password:密码
sf.connect(username = "root",password="areyouok1")


SFTPClient.from_transport(加密管道)
建立一个客户端对象,通过ssh transport操作远程文件
加密管道:之前创建的sf对象
sftp = paramiko.SFTPClient.from_transport(sf)

get(远程文件,本地文件) 从远程下载指定文件存到本地
远程文件名
本地文件名
sftp.get(remotepath,localpath)


put(本地文件,远程文件) 从本地上传指定文件到远程路径
本地文件名
远程文件名

sftp.put(localpath,remotepath)
listdir(远程路径) 列出远程指定路径的文件夹 远程路径名 sftp.listdir("..")

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
密码登陆方式代码如下:
#!/usr/bin/env python
# coding:utf-8
import paramiko
# 创建SSH对象
ssh = paramiko.SSHClient()
# 访问未知主机时候的策略,允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='172.16.1.101', port=22, username='wgw', password='123456')
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read().decode
#打印远程命令的执行结果
print(result)
# 关闭连接
ssh.close()

唯一要注意的就是遇到未知主机的时候,ssh的处理策略。这个要设置好。不然know_hosts文件里没有的主机在第一次登陆的时候会被拒绝掉。

使用SSH秘钥登陆的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python
# coding:utf-8
import paramiko
#指定用于登录其他主机的私钥文件的存储位置
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器的时候通过pkey关键字替代password关键字
ssh.connect(hostname='172.16.1.101', port=22, username='wgw', pkey=private_key)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read().decode()
print(result)
# 关闭连接
ssh.close()

通过秘钥登陆的用户和密码登陆大同小异,只需定义私钥文件的位置然后引用pkey关键字就好了。

使用密码和SFTP命令上传和下载文件的代码如下:

1
2
3
4
5
6
7
8
9
import paramiko
transport = paramiko.Transport(('hostname',22))
transport.connect(username='wupeiqi',password='123')
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()

使用秘钥和SFTP命令上传和下载文件的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
#创建transport对象
transport = paramiko.Transport(('hostname', 22))
#通过connect方法创建远程连接
transport.connect(username='wgw', pkey=private_key )
#调用SFTPClient填写刚才创建的transport对象来创建一个sftp对象
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()

代码不难,但是从代码里可以到实现ssh和sftp的时候。创建连接时使用的方法不一样。

SSH是使用SSHClient()里面的connect方法创建的

1
2
ssh = paramiko.SSHClient()
ssh.connect(hostname='172.16.1.101', port=22, username='wgw', password='123456')

SFTP使用的Transport()里面的connetc方法创建的

1
2
transport = paramiko.Transport(('172.16.1.101',22))
transport.connect(username='wgw',password='123456')

两个都是connect方法有什么区别和联系呢?其实paramiko.SSHClient().connect()这个方法的内部实现调用的就是Transport().connect()这个方法。所以可以认为Transport()是paramiko里面创建连接的通用方法。那我们通过Transport方法来改写一下SSH的功能

1
2
3
4
5
6
7
8
9
10
11
import paramiko
#调用Transport方法与实现SFTP的连接功能一样,创建连接
transport = paramiko.Transport(('172.16.1.101', 22))
transport.connect(username='wgw', password='123456')
#这个方法还是必须要加上的还需要调用exec_command()等方法使用
ssh = paramiko.SSHClient()
#用这一句代替ssh.connect()方法
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()
transport.close()

这样如果我们要实现一个可以远程操作主机的程序,那么程序的远程执行命令和传输文件等功能就可以写到一个类里面了。示意代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import paramiko
class my_paramiko(object):
def __init__(self,ip,port):
self.ip=ip
self.port=int(port)
#定义登录被管理主机时使用的用户
self.manager='admin'
#指定登录各个主机时所使用的秘钥文件位置
self.key=paramiko.RSAKey.from_private_key_file('/home/wgw/.ssh/id_rsa')
def connect(self):
"""
这个方法用于调用paramiko创建连接。
"""
#创建连接实例
transport = paramiko.Transport((self.ip,self.port))
transport.connect(username=self.manager, pkey=self.key)
self.__transport=transport
def cmd(self,user_cmd):
"""
这个方法用于实现在远程主机上执行命令
"""
#调用连接方法连接服务器
self.connect()
#调用paramiko的SSH方法实现远程执行命令
ssh = paramiko.SSHClient()
ssh._transport=self.__transport
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#远程执行命令
ssh.exec_command(user_cmd)
#执行命令后管理远程连接
ssh.close()

def excute_upload(self,local_file,remote_file):
"""
这个方法用于实现,上传文件到远程的功能。要求用户输入本地文件路径和远程文件
路径。
"""
#调用连接方法连接服务器
self.connect()
#调用paramiko的sftp方法实现远程上传命令
sftp = paramiko.SFTPClient.from_transport(self.__transport)
#调用sftp.put方法把本地文件上传到服务器上。
sftp.put(local_file,remote_file)